package binding

import (
	"fmt"
	"reflect"
	"strconv"
	"time"
)

// 字符串转换为整数
func ParseInt(s string) int64 {
	n, _ := strconv.ParseInt(s, 10, 64)
	return n
}

// 字符串转换为浮点数
func ParseFloat(s string) float64 {
	n, _ := strconv.ParseFloat(s, 64)
	return n
}

// 转换为map
func ToMap(val interface{}) (map[string]interface{}, error) {
	switch ret := val.(type) {
	case map[string]interface{}:
		return ret, nil
	default:
		return nil, typeError(val, "map")
	}
}

// 转换为日期
func ToTime(val interface{}, layout string) (time.Time, error) {
	switch ret := val.(type) {
	case string:
		return time.ParseInLocation(layout, ret, time.Local)
	default:
		return time.Time{}, typeError(val, "time")
	}
}

// 转换为slice
func ToSlice(val interface{}) ([]interface{}, error) {
	switch ret := val.(type) {
	case []interface{}:
		return ret, nil
	default:
		return nil, typeError(val, "slice")
	}
}

// 转换为int64
func ToInt64(val interface{}) (int64, error) {
	switch ret := val.(type) {
	case int64:
		return ret, nil
	case int:
		return int64(ret), nil
	case int8:
		return int64(ret), nil
	case int16:
		return int64(ret), nil
	case int32:
		return int64(ret), nil
	case uint:
		return int64(ret), nil
	case uint8:
		return int64(ret), nil
	case uint16:
		return int64(ret), nil
	case uint32:
		return int64(ret), nil
	case uint64:
		return int64(ret), nil
	case float32:
		return int64(ret), nil
	case float64:
		return int64(ret), nil
	case string:
		return strconv.ParseInt(ret, 10, 64)
	default:
		return -1, typeError(ret, "int")
	}
}

func typeError(v interface{}, t string) error {
	tn := reflect.TypeOf(v)
	return fmt.Errorf("value %s type is %s not %s", fmt.Sprint(v), tn.Kind().String(), t)
}

// 转换为uint64
func ToUint64(val interface{}) (uint64, error) {
	switch ret := val.(type) {
	case uint64:
		return ret, nil
	case int:
		if ret < 0 {
			return 0, typeError(ret, "uint")
		}
		return uint64(ret), nil
	case int8:
		if ret < 0 {
			return 0, typeError(ret, "uint")
		}
		return uint64(ret), nil
	case int16:
		if ret < 0 {
			return 0, typeError(ret, "uint")
		}
		return uint64(ret), nil

	case int32:
		if ret < 0 {
			return 0, typeError(ret, "uint")
		}
		return uint64(ret), nil
	case int64:
		if ret < 0 {
			return 0, typeError(ret, "uint")
		}
		return uint64(ret), nil
	case uint:
		return uint64(ret), nil
	case uint8:
		return uint64(ret), nil
	case uint16:
		return uint64(ret), nil
	case uint32:
		return uint64(ret), nil
	case float32:
		return uint64(ret), nil
	case float64:
		return uint64(ret), nil
	case string:
		return strconv.ParseUint(ret, 10, 64)
	default:
		return 0, typeError(ret, "uint")
	}
}

// 转换为string
func ToString(val interface{}) (str string, err error) {
	switch ret := val.(type) {
	case string:
		str, err = ret, nil
	case int:
		str, err = strconv.FormatInt(int64(ret), 10), nil
	case int8:
		str, err = strconv.FormatInt(int64(ret), 10), nil
	case int16:
		str, err = strconv.FormatInt(int64(ret), 10), nil
	case int32:
		str, err = strconv.FormatInt(int64(ret), 10), nil
	case int64:
		str, err = strconv.FormatInt(int64(ret), 10), nil
	case uint:
		str, err = strconv.FormatUint(uint64(ret), 10), nil
	case uint8:
		str, err = strconv.FormatUint(uint64(ret), 10), nil
	case uint16:
		str, err = strconv.FormatUint(uint64(ret), 10), nil
	case uint32:
		str, err = strconv.FormatUint(uint64(ret), 10), nil
	case uint64:
		str, err = strconv.FormatUint(uint64(ret), 10), nil
	case bool:
		str, err = strconv.FormatBool(ret), nil
	case float32:
		str, err = strconv.FormatFloat(float64(ret), 'f', -1, 64), nil
	case float64:
		str, err = strconv.FormatFloat(float64(ret), 'f', -1, 64), nil
	default:
		str, err = "", typeError(ret, "string")
	}
	return
}

// 转换为bool类型,大于0的数字=true,小于0的数字=false
func ToBool(val interface{}) (bool, error) {
	switch ret := val.(type) {
	case bool:
		return ret, nil
	case int:
		return ret > 0, nil
	case int8:
		return ret > 0, nil
	case int16:
		return ret > 0, nil
	case int32:
		return ret > 0, nil
	case int64:
		return ret > 0, nil
	case float32:
		return ret > 0, nil
	case float64:
		return ret > 0, nil
	case uint:
		return ret > 0, nil
	case uint8:
		return ret > 0, nil
	case uint16:
		return ret > 0, nil
	case uint32:
		return ret > 0, nil
	case uint64:
		return ret > 0, nil
	case string:
		return strconv.ParseBool(ret)
	default:
		return false, typeError(val, "bool")
	}
}

// 转换为float类型
func ToFloat64(val interface{}) (float64, error) {
	switch ret := val.(type) {
	case int:
		return float64(ret), nil
	case int8:
		return float64(ret), nil
	case int16:
		return float64(ret), nil
	case int32:
		return float64(ret), nil
	case int64:
		return float64(ret), nil
	case uint:
		return float64(ret), nil
	case uint8:
		return float64(ret), nil
	case uint16:
		return float64(ret), nil
	case uint32:
		return float64(ret), nil
	case uint64:
		return float64(ret), nil
	case float32:
		return float64(ret), nil
	case float64:
		return ret, nil
	case string:
		return strconv.ParseFloat(ret, 64)
	default:
		return -1, typeError(ret, "float64")
	}
}
